﻿using System;
using System.IO;
using CompactFormatter;

namespace PowerAwareBluetooth.Controller.IO
{
    /// <summary>
    /// handles the saving and loading of the saved data
    /// </summary>
    public static class IOManager
    {
        #region SaveType enum

        public enum SaveType
        {
            USER_DEFINED_RULES,
            LEARNED_TIMELINE,
            CELL_TOWER_INFO,
        } ;

        #endregion

        private const string LEARNED_TIME_LINE = @"LearnedTimeLine.bin";
        private const string USER_RULES_DATA_FILE = @"UserDefinedRules.bin";
        private const string CELL_TOWER_INFO_FILE = @"CellTowerInfo.bin";

        public static string CurrentDirectory
        {
            get
            {
                return
                    System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
            }
        }
        
        public static void Save(object dataToSave, SaveType saveType)
        {
            string path = GetPath(saveType);
            try
            {
                Save(dataToSave, path);
            }
            catch (Exception e)
            {
                // do nothing
            }
        }
        
        public static object Load(SaveType saveType)
        {
            string path = GetPath(saveType);
            return Load(path);
        }

        private static void Save(object dataToSave, string path)
        {
            SerializeObject(path, dataToSave);
        }

        /// <summary>
        /// loads the object from the saved file.
        /// if an error occurred while trying to load the file then
        /// null is returned
        /// </summary>
        /// <returns></returns>
        private static object Load(string path)
        {
            try
            {
                return DeserializeObject(path);
            }
            catch (Exception e)
            {
                return null;
            }
        }

        private static string GetPath(SaveType saveType)
        {
            string path = null;
            switch (saveType)
            {
                case SaveType.USER_DEFINED_RULES:
                    path = Path.Combine(CurrentDirectory, USER_RULES_DATA_FILE);
                    break;
                case SaveType.LEARNED_TIMELINE:
                    path = Path.Combine(CurrentDirectory, LEARNED_TIME_LINE);
                    break;
                case SaveType.CELL_TOWER_INFO:
                    path = Path.Combine(CurrentDirectory, CELL_TOWER_INFO_FILE);
                    break;
            }
            return path;
        }

        /// <summary>
        /// serializing a graph to a file
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="graph"></param>
        private static void SerializeObject(string filename, object graph)
        {
            Directory.CreateDirectory(Path.GetDirectoryName(filename));
            using (Stream stream = new FileStream(filename, FileMode.OpenOrCreate))
            {
                BinaryWriter binaryWriter = new BinaryWriter(stream);
                CompactFormatterPlus compactFormatterPlus = new CompactFormatterPlus();
                compactFormatterPlus.Serialize(stream, graph);
            }
        }

        /// <summary>
        /// deserializing a file to a graph
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private static object DeserializeObject(string filename)
        {
            using (Stream stream = new FileStream(filename, FileMode.Open))
            {
                CompactFormatterPlus compactFormatterPlus = new CompactFormatterPlus();
                object obj = compactFormatterPlus.Deserialize(stream);
                return obj;
            }
        }
        
        public static void TryDelete(SaveType saveType)
        {
            try
            {
                string path = GetPath(saveType);
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
            catch (Exception e)
            {
                // do nothing
            }

        }
    }
}